package com.fee1in;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

class Executor {
    private Configuration configuration;

    public Executor(Configuration configuration) {
        this.configuration = configuration;
    }

    public List executeQuery(String statement) throws Exception {
        Map<String, MappedStatement> mappedStatements = configuration.mappedStatements;
        MappedStatement mappedStatement = mappedStatements.get(statement);
        String sql = mappedStatement.getSql();

        DataSource dataSource = configuration.dataSource;
        try (Connection connection = dataSource.getConnection();
             PreparedStatement ps = connection.prepareStatement(sql);
             ResultSet rs = ps.executeQuery();) {
            return handleResult(mappedStatement, rs);
        }

    }

    private List handleResult(MappedStatement mappedStatement, ResultSet rs) throws Exception {

        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        List<String> columnNames = new ArrayList<String>();
        for (int i = 1; i <= columnCount; i++) {
            columnNames.add(metaData.getColumnName(i));
        }
        List list = new ArrayList();

        Class<?> clazz = Class.forName(mappedStatement.getResultType());
        Method[] methods = clazz.getMethods();
        while (rs.next()) {
            Object object = clazz.newInstance();

            for (String columnName : columnNames) {
                for (Method method : methods) {
                    String methodName = method.getName();
                    if (("set" + columnName).equalsIgnoreCase(methodName)) {
                        method.invoke(object, rs.getObject(columnName));
                    }
                }
            }
            list.add(object);
        }

        return list;

    }
}
